home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
gc
/
GCfinalize.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-04
|
9KB
|
431 lines
/* begincopyright
Copyright (c) 1988,1990 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
endcopyright */
/*
* finalize.c
*
* PCR finalization.
* This exports to the PCedar PFinalize interface.
*
* Mark Weiser
* Demers, February 12, 1990 10:43:05 am PST
* Boehm, March 6, 1990 6:14:46 pm PST
*/
#ifdef FINALIZE
#include "xr/Errno.h"
#include <xr/GCPrivate.h>
#include <xr/ThreadsMsg.h>
/*
* Finalization queues
*/
XR_FinalizationQueue
XR_NewFQ ()
{
XR_FinalizationQueue fq;
fq = (XR_FinalizationQueue)
XR_malloc(sizeof(struct XR_FinalizationQueueStructure));
fq->head = NIL;
fq->tail = NIL;
XR_InitializeCondition(&(fq->fqNonempty), XR_WAIT_FOREVER);
XR_EnableAborts(&(fq->fqNonempty));
return fq;
}
XR_FinalizationHandle
XR_FQNextNoAbort (fq)
XR_FinalizationQueue fq;
/*
Like FQNext, but returns NIL rather than raising aborted.
*/
{
XR_FinalizationHandle h;
if( fq == NIL ) return NIL;
XR_MonitorEntry( &(GC_allocate_ml) );
while( (h = fq->head) == NIL ) {
if( XR_WaitCV( &(fq->fqNonempty), &(GC_allocate_ml) ) != 0 ) {
XR_SetErrno(XR_EABORTED);
goto Out;
}
}
if( (fq->head = h->next) == NIL ) fq->tail = NIL;
h->associatedFQ = NIL;
h->next = NIL;
Out:
XR_MonitorExit( &(GC_allocate_ml) );
return h;
}
/* ... to be called only from a thread: */
static void
XR_RemoveFromFQInternal (h)
XR_FinalizationHandle h;
{
XR_FinalizationQueue fq;
XR_FinalizationHandle p, prev;
fq = h->associatedFQ;
p = fq->head;
prev = NIL;
for(;;) {
if( p == h ) {
if( prev == NIL ) fq->head = p->next; else prev->next = p->next;
if( fq->tail == p ) fq->tail = prev;
p->next = NIL;
p->associatedFQ = NIL;
break;
}
if( p == NIL ) XR_Panic("RemoveFromFQInternal 0");
prev = p;
p = p->next;
}
}
/* ... to be called only from an iop: */
static void
XR_InsertOnFQInternal(h)
XR_FinalizationHandle h;
{
XR_FinalizationQueue fq;
XR_FinalizationHandle tl;
fq = h->associatedFQ;
if( (tl = fq->tail) == NIL ) {
fq->head = h;
XR_NakedNotify(&(fq->fqNonempty));
} else {
tl->next = h;
}
fq->tail = h;
h->next = NIL;
}
bool
XR_FQEmpty(fq)
XR_FinalizationQueue fq;
{
return ((fq == NIL) || (fq->head == NIL));
}
/*
* Controlling finalization of objects
*/
XR_FinalizationHandle
XR_NewFinalizationHandle()
{
register XR_FinalizationHandle h =
(XR_FinalizationHandle) XR_malloc( sizeof(struct XR_FinalizableObjectStructure) );
h->firstword = 0;
h->secondword = 0;
h->associatedFQ = NIL;
h->next = NIL;
return h;
}
void
XR_EnableFinalization(object, fq, h)
XR_Pointer object;
XR_FinalizationQueue fq;
XR_FinalizationHandle h;
{
if( (object == NIL) || (fq == NIL) || (h == NIL) ) return;
/* caller gets storage outside the monitor */
XR_MonitorEntry( &GC_allocate_ml );
XR_StoreDisguised(object, h);
h->associatedFQ = fq;
h->next = GC_finalizeListHead;
GC_finalizeListHead = h;
XR_MonitorExit( &GC_allocate_ml );
}
XR_FinalizationState
XR_DisableFinalization(h)
XR_FinalizationHandle h;
{
XR_FinalizationHandle p, prev;
XR_FinalizationState q;
word w;
if( h == NIL ) return fzsDisabled;
XR_MonitorEntry( &GC_allocate_ml);
if( h->associatedFQ == NIL ) {
q = fzsDisabled;
} else if( !XR_IsDisguised(h) ) {
q = fzsOnFQ;
XR_RemoveFromFQInternal(h);
} else {
q = fzsEnabled;
p = GC_finalizeListHead;
prev = NIL;
for(;;) {
if( p == NIL ) break;
if( p == h ) {
if( prev == NIL )
GC_finalizeListHead = p->next;
else
prev->next = p->next;
break;
}
prev = p;
p = p->next;
}
w = XR_FetchFromDisguised(h);
XR_StoreUndisguised(w,h);
h->associatedFQ = NIL;
}
h->next = NIL;
XR_MonitorExit( &GC_allocate_ml );
return q;
}
XR_FinalizationState
XR_ReenableFinalization(h, fq)
XR_FinalizationHandle h;
XR_FinalizationQueue fq;
{
XR_FinalizationState q;
word object;
/* arguably the following is incorrect if fq == NIL */
/* but that's a client error anyway. */
if( (h == NIL) || (fq == NIL) ) return fzsDisabled;
XR_MonitorEntry( &GC_allocate_ml );
if( XR_IsDisguised(h) ) {
q = fzsEnabled;
} else {
if( h->associatedFQ == NIL ) {
q = fzsDisabled;
} else {
q = fzsOnFQ;
XR_RemoveFromFQInternal(h);
}
object = XR_FetchFromUndisguised(h);
XR_StoreDisguised(object,h);
h->next = GC_finalizeListHead;
GC_finalizeListHead = h;
}
h->associatedFQ = fq;
XR_MonitorExit( &GC_allocate_ml );
return q;
}
XR_FinalizationState
XR_GetFinalizationState(h)
XR_FinalizationHandle h;
{
XR_FinalizationState q;
if( h == NIL ) return fzsDisabled;
XR_MonitorEntry( &GC_allocate_ml );
if( XR_IsDisguised(h) ) {
q = fzsEnabled;
} else if( h->associatedFQ != NIL ) {
q = fzsOnFQ;
} else {
q = fzsDisabled;
}
XR_MonitorExit( &GC_allocate_ml );
return q;
}
XR_Pointer
XR_HandleToObject(h)
XR_FinalizationHandle h;
{
word w;
if( h == NIL ) return NIL;
XR_MonitorEntry( &GC_allocate_ml );
if( XR_IsDisguised(h) ) {
w = XR_FetchFromDisguised(h);
} else {
w = XR_FetchFromUndisguised(h);
}
XR_MonitorExit( &GC_allocate_ml );
return (XR_Pointer)w;
}
/*
*
* --------- below here, routines are all private to the collector ---------
*
*/
static bool
marked(p)
register struct obj *p;
{
register struct hblk * h;
register long word_no;
register bool result;
register unsigned long sz;
h = HBLKPTR(p);
# ifdef INTERIOR_POINTERS
if (!is_hblk(h)) {
char m = get_map(h);
while (m > 0 && m < 0x7f) {
h -= m;
m = get_map(h);
}
}
sz = HB_SIZE(h);
# endif
word_no = WORD_NO(p, h);
# ifdef INTERIOR_POINTERS
word_no = adjusted_word_no(word_no,sz);
# endif
result = mark_bit(h, word_no);
return (result);
}
static void
mark_through(p)
char *p;
/*
Queue everything for marking that p points to, but not p itself.
Assumes p is a legitimate pointer.
*/
{
unsigned int sz;
struct hblk * h;
register long word_no;
h = HBLKPTR(p);
# ifdef INTERIOR_POINTERS
if (!is_hblk(h)) {
char m = get_map(h);
while (m > 0 && m < 0x7f) {
h -= m;
m = get_map(h);
}
}
# endif
word_no = WORD_NO(p, h);
sz = hb_sz(h);
if (sz < 0) /* Pointerfree */ return;
# ifdef INTERIOR_POINTERS
word_no = adjusted_word_no(word_no,sz);
p = (char *)h + WORDS_TO_BYTES(word_no);
# endif
(void)GC_mark_all(p, p+WORDS_TO_BYTES(sz),
ALIGNMENT, ALL_POINTERS, FALSE /* Dont coerce pointers */);
}
void
GC_TraceFinalizableObjects()
{
XR_FinalizationHandle h, prev, next;
struct obj *p;
/*
* walk down the list, marking everything pointed to,
* but not (directly) the objects themselves
*/
if (GC_mark_stack_top != GC_mark_stack_bottom) {
GC_abort("GC_TraceFinalizableObjects 0");
}
for( h = GC_finalizeListHead; h != NIL; h = h->next ) {
p = (struct obj *) XR_FetchFromDisguised(h);
if( !marked(p) ) {
mark_through(p);
if (XR_verbosity >= XR_VERBOSITY_STATS) {
GC_mark(ALIGNMENT);
if (marked(p)) {
GC_printf("Finalization cycle involving 0x%X\n", p);
}
}
}
}
GC_mark(ALIGNMENT);
/*
* Find still unmarked objects, mark them,
* and put them on finalization queues.
*/
if (GC_mark_stack_top != GC_mark_stack_bottom) {
GC_abort("GC_TraceFinalizableObjects 1");
}
prev = NIL;
for( h = GC_finalizeListHead; h != NIL; h = next ) {
next = h->next; /* remember now, because we may throw h away */
p = (struct obj *) XR_FetchFromDisguised(h);
if (! marked(p)) {
/* remove from list */
if (prev != NIL) {
prev->next = h->next;
} else {
GC_finalizeListHead = h->next;
}
/* put on finalization queue */
XR_StoreUndisguised(p,h);
XR_InsertOnFQInternal(h);
/* push the pointer on the mark stack for later */
if (quicktest(p)) {
PUSH_MS((word) p);
}
/* don't update prev here, since we deleted h */
} else {
prev = h;
}
} /* done walking list for finalizing */
GC_mark(ALIGNMENT); /* mark finalized objects */
}
#endif /* FINALIZE */